/*
 * Copyright 2019 聂钊 nz@qdigo.com
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a to of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.qdigo.ebike.common.core.util.geo;

import com.google.common.collect.Lists;

import java.awt.geom.Point2D;
import java.util.List;

/**
 * Created by niezhao on 2017/11/22.
 */
public class GeoChinaUtil {

    //http://www.cnblogs.com/Aimeast/archive/2012/08/09/2629614.html


    private static class Rectangle {
        public Rectangle(double lng1, double lat1, double lng2, double lat2) {
            this.west = Math.min(lng1, lng2);
            this.north = Math.max(lat1, lat2);
            this.east = Math.max(lng1, lng2);
            this.south = Math.min(lat1, lat2);
        }

        private double west; //左
        private double north; //上
        private double east; //东
        private double south; //南
    }

    private static boolean isInRect(Rectangle rect, double lon, double lat) {
        return rect.west <= lon && rect.east >= lon && rect.north >= lat && rect.south <= lat;
    }

    //China region - raw data
    private static final Rectangle[] region = {
        new Rectangle(79.446200, 49.220400, 96.330000, 42.889900),
        new Rectangle(109.687200, 54.141500, 135.000200, 39.374200),
        new Rectangle(73.124600, 42.889900, 124.143255, 29.529700),
        new Rectangle(82.968400, 29.529700, 97.035200, 26.718600),
        new Rectangle(97.025300, 29.529700, 124.367395, 20.414096),
        new Rectangle(107.975793, 20.414096, 111.744104, 17.871542)
    };

    //China excluded region - raw data
    private static final Rectangle[] exclude = {
        new Rectangle(119.921265, 25.398623, 122.497559, 21.785006),
        new Rectangle(101.865200, 22.284000, 106.665000, 20.098800),
        new Rectangle(106.452500, 21.542200, 108.051000, 20.487800),
        new Rectangle(109.032300, 55.817500, 119.127000, 50.325700),
        new Rectangle(127.456800, 55.817500, 137.022700, 49.557400),
        new Rectangle(131.266200, 44.892200, 137.022700, 42.569200),
        // hongkong
        new Rectangle(113.837108, 22.44151, 114.408397, 22.167709)
    };

    public static boolean isInChinaOnce(double lng, double lat) {
        for (Rectangle rect : region) {
            if (isInRect(rect, lng, lat)) {
                for (Rectangle anExclude : exclude) {
                    if (isInRect(anExclude, lng, lat)) {
                        return false;
                    }
                }
                return true;
            }
        }
        return false;
    }

    public static boolean isInChinaTwice(double lng, double lat) {
        if (GeoUtil.isInPolygon(lat, lng, mainland)) {
            return true;
        } else if (GeoUtil.isInPolygon(lat, lng, taiwan)) {
            return true;
        } else if (GeoUtil.isInPolygon(lat, lng, hainan)) {
            return true;
        } else if (GeoUtil.isInPolygon(lat, lng, chongming)) {
            return true;
        } else {
            return false;
        }
    }

    public static boolean isInChina(double lng, double lat) {
        if (isInChinaOnce(lng, lat)) {
            return true;
        } else if (isInChinaTwice(lng, lat)) {
            return true;
        } else {
            return false;
        }
    }

    private static final List<Point2D.Double> mainland = Lists.newArrayList(
        new Point2D.Double(27.32083, 88.91693),
        new Point2D.Double(27.54243, 88.76464),
        new Point2D.Double(28.00805, 88.83575),
        new Point2D.Double(28.1168, 88.62435),
        new Point2D.Double(27.86605, 88.14279),
        new Point2D.Double(27.82305, 87.19275),
        new Point2D.Double(28.11166, 86.69527),
        new Point2D.Double(27.90888, 86.45137),
        new Point2D.Double(28.15805, 86.19769),
        new Point2D.Double(27.88625, 86.0054),
        new Point2D.Double(28.27916, 85.72137),
        new Point2D.Double(28.30666, 85.11095),
        new Point2D.Double(28.59104, 85.19518),
        new Point2D.Double(28.54444, 84.84665),
        new Point2D.Double(28.73402, 84.48623),
        new Point2D.Double(29.26097, 84.11651),
        new Point2D.Double(29.18902, 83.5479),
        new Point2D.Double(29.63166, 83.19109),
        new Point2D.Double(30.06923, 82.17525),
        new Point2D.Double(30.33444, 82.11123),
        new Point2D.Double(30.385, 81.42623),
        new Point2D.Double(30.01194, 81.23221),
        new Point2D.Double(30.20435, 81.02536),
        new Point2D.Double(30.57552, 80.207),
        new Point2D.Double(30.73374, 80.25423),
        new Point2D.Double(30.96583, 79.86304),
        new Point2D.Double(30.95708, 79.55429),
        new Point2D.Double(31.43729, 79.08082),
        new Point2D.Double(31.30895, 78.76825),
        new Point2D.Double(31.96847, 78.77075),
        new Point2D.Double(32.24304, 78.47594),
        new Point2D.Double(32.5561, 78.40595),
        new Point2D.Double(32.63902, 78.74623),
        new Point2D.Double(32.35083, 78.9711),
        new Point2D.Double(32.75666, 79.52874),
        new Point2D.Double(33.09944, 79.37511),
        new Point2D.Double(33.42863, 78.93623),
        new Point2D.Double(33.52041, 78.81387),
        new Point2D.Double(34.06833, 78.73581),
        new Point2D.Double(34.35001, 78.98535),
        new Point2D.Double(34.6118, 78.33707),
        new Point2D.Double(35.28069, 78.02305),
        new Point2D.Double(35.49902, 78.0718),
        new Point2D.Double(35.50133, 77.82393),
        new Point2D.Double(35.6125, 76.89526),
        new Point2D.Double(35.90665, 76.55304),
        new Point2D.Double(35.81458, 76.18061),
        new Point2D.Double(36.07082, 75.92887),
        new Point2D.Double(36.23751, 76.04166),
        new Point2D.Double(36.66343, 75.85984),
        new Point2D.Double(36.73169, 75.45179),
        new Point2D.Double(36.91156, 75.39902),
        new Point2D.Double(36.99719, 75.14787),
        new Point2D.Double(37.02782, 74.56543),
        new Point2D.Double(37.17, 74.39089),
        new Point2D.Double(37.23733, 74.91574),
        new Point2D.Double(37.40659, 75.18748),
        new Point2D.Double(37.65243, 74.9036),
        new Point2D.Double(38.47256, 74.85442),
        new Point2D.Double(38.67438, 74.35471),
        new Point2D.Double(38.61271, 73.81401),
        new Point2D.Double(38.88653, 73.70818),
        new Point2D.Double(38.97256, 73.85235),
        new Point2D.Double(39.23569, 73.62005),
        new Point2D.Double(39.45483, 73.65569),
        new Point2D.Double(39.59965, 73.95471),
        new Point2D.Double(39.76896, 73.8429),
        new Point2D.Double(40.04202, 73.99096),
        new Point2D.Double(40.32792, 74.88089),
        new Point2D.Double(40.51723, 74.8588),
        new Point2D.Double(40.45042, 75.23394),
        new Point2D.Double(40.64452, 75.58284),
        new Point2D.Double(40.298, 75.70374),
        new Point2D.Double(40.35324, 76.3344),
        new Point2D.Double(41.01258, 76.87067),
        new Point2D.Double(41.04079, 78.08083),
        new Point2D.Double(41.39286, 78.39554),
        new Point2D.Double(42.03954, 80.24513),
        new Point2D.Double(42.19622, 80.23402),
        new Point2D.Double(42.63245, 80.15804),
        new Point2D.Double(42.81565, 80.25796),
        new Point2D.Double(42.88545, 80.57226),
        new Point2D.Double(43.02906, 80.38405),
        new Point2D.Double(43.1683, 80.81526),
        new Point2D.Double(44.11378, 80.36887),
        new Point2D.Double(44.6358, 80.38499),
        new Point2D.Double(44.73408, 80.51589),
        new Point2D.Double(44.90282, 79.87106),
        new Point2D.Double(45.3497, 81.67928),
        new Point2D.Double(45.15748, 81.94803),
        new Point2D.Double(45.13303, 82.56638),
        new Point2D.Double(45.43581, 82.64624),
        new Point2D.Double(45.5831, 82.32179),
        new Point2D.Double(47.20061, 83.03443),
        new Point2D.Double(46.97332, 83.93026),
        new Point2D.Double(46.99361, 84.67804),
        new Point2D.Double(46.8277, 84.80318),
        new Point2D.Double(47.0591, 85.52257),
        new Point2D.Double(47.26221, 85.70139),
        new Point2D.Double(47.93721, 85.53707),
        new Point2D.Double(48.39333, 85.76596),
        new Point2D.Double(48.54277, 86.59791),
        new Point2D.Double(49.1102, 86.87602),
        new Point2D.Double(49.09262, 87.34821),
        new Point2D.Double(49.17295, 87.8407),
        new Point2D.Double(48.98304, 87.89291),
        new Point2D.Double(48.88103, 87.7611),
        new Point2D.Double(48.73499, 88.05942),
        new Point2D.Double(48.56541, 87.99194),
        new Point2D.Double(48.40582, 88.51679),
        new Point2D.Double(48.21193, 88.61179),
        new Point2D.Double(47.99374, 89.08514),
        new Point2D.Double(47.88791, 90.07096),
        new Point2D.Double(46.95221, 90.9136),
        new Point2D.Double(46.57735, 91.07027),
        new Point2D.Double(46.29694, 90.92151),
        new Point2D.Double(46.01735, 91.02651),
        new Point2D.Double(45.57972, 90.68193),
        new Point2D.Double(45.25305, 90.89694),
        new Point2D.Double(45.07729, 91.56088),
        new Point2D.Double(44.95721, 93.5547),
        new Point2D.Double(44.35499, 94.71735),
        new Point2D.Double(44.29416, 95.41061),
        new Point2D.Double(44.01937, 95.34109),
        new Point2D.Double(43.99311, 95.53339),
        new Point2D.Double(43.28388, 95.87901),
        new Point2D.Double(42.73499, 96.38206),
        new Point2D.Double(42.79583, 97.1654),
        new Point2D.Double(42.57194, 99.51012),
        new Point2D.Double(42.67707, 100.8425),
        new Point2D.Double(42.50972, 101.8147),
        new Point2D.Double(42.23333, 102.0772),
        new Point2D.Double(41.88721, 103.4164),
        new Point2D.Double(41.87721, 104.5267),
        new Point2D.Double(41.67068, 104.5237),
        new Point2D.Double(41.58666, 105.0065),
        new Point2D.Double(42.46624, 107.4758),
        new Point2D.Double(42.42999, 109.3107),
        new Point2D.Double(42.64576, 110.1064),
        new Point2D.Double(43.31694, 110.9897),
        new Point2D.Double(43.69221, 111.9583),
        new Point2D.Double(44.37527, 111.4214),
        new Point2D.Double(45.04944, 111.873),
        new Point2D.Double(45.08055, 112.4272),
        new Point2D.Double(44.8461, 112.853),
        new Point2D.Double(44.74527, 113.638),
        new Point2D.Double(45.38943, 114.5453),
        new Point2D.Double(45.4586, 115.7019),
        new Point2D.Double(45.72193, 116.2104),
        new Point2D.Double(46.29583, 116.5855),
        new Point2D.Double(46.41888, 117.3755),
        new Point2D.Double(46.57069, 117.425),
        new Point2D.Double(46.53645, 117.8455),
        new Point2D.Double(46.73638, 118.3147),
        new Point2D.Double(46.59895, 119.7068),
        new Point2D.Double(46.71513, 119.9315),
        new Point2D.Double(46.90221, 119.9225),
        new Point2D.Double(47.66499, 119.125),
        new Point2D.Double(47.99475, 118.5393),
        new Point2D.Double(48.01125, 117.8046),
        new Point2D.Double(47.65741, 117.3827),
        new Point2D.Double(47.88805, 116.8747),
        new Point2D.Double(47.87819, 116.2624),
        new Point2D.Double(47.69186, 115.9231),
        new Point2D.Double(47.91749, 115.5944),
        new Point2D.Double(48.14353, 115.5491),
        new Point2D.Double(48.25249, 115.8358),
        new Point2D.Double(48.52055, 115.8111),
        new Point2D.Double(49.83047, 116.7114),
        new Point2D.Double(49.52058, 117.8747),
        new Point2D.Double(49.92263, 118.5746),
        new Point2D.Double(50.09631, 119.321),
        new Point2D.Double(50.33028, 119.36),
        new Point2D.Double(50.39027, 119.1386),
        new Point2D.Double(51.62083, 120.0641),
        new Point2D.Double(52.115, 120.7767),
        new Point2D.Double(52.34423, 120.6259),
        new Point2D.Double(52.54267, 120.7122),
        new Point2D.Double(52.58805, 120.0819),
        new Point2D.Double(52.76819, 120.0314),
        new Point2D.Double(53.26374, 120.8307),
        new Point2D.Double(53.54361, 123.6147),
        new Point2D.Double(53.18832, 124.4933),
        new Point2D.Double(53.05027, 125.62),
        new Point2D.Double(52.8752, 125.6573),
        new Point2D.Double(52.75722, 126.0968),
        new Point2D.Double(52.5761, 125.9943),
        new Point2D.Double(52.12694, 126.555),
        new Point2D.Double(51.99437, 126.4412),
        new Point2D.Double(51.38138, 126.9139),
        new Point2D.Double(51.26555, 126.8176),
        new Point2D.Double(51.31923, 126.9689),
        new Point2D.Double(51.05825, 126.9331),
        new Point2D.Double(50.74138, 127.2919),
        new Point2D.Double(50.31472, 127.334),
        new Point2D.Double(50.20856, 127.5861),
        new Point2D.Double(49.80588, 127.515),
        new Point2D.Double(49.58665, 127.838),
        new Point2D.Double(49.58443, 128.7119),
        new Point2D.Double(49.34676, 129.1118),
        new Point2D.Double(49.4158, 129.4902),
        new Point2D.Double(48.86464, 130.2246),
        new Point2D.Double(48.86041, 130.674),
        new Point2D.Double(48.60576, 130.5236),
        new Point2D.Double(48.3268, 130.824),
        new Point2D.Double(48.10839, 130.6598),
        new Point2D.Double(47.68721, 130.9922),
        new Point2D.Double(47.71027, 132.5211),
        new Point2D.Double(48.09888, 133.0827),
        new Point2D.Double(48.06888, 133.4843),
        new Point2D.Double(48.39112, 134.4153),
        new Point2D.Double(48.26713, 134.7408),
        new Point2D.Double(47.99207, 134.5576),
        new Point2D.Double(47.70027, 134.7608),
        new Point2D.Double(47.32333, 134.1825),
        new Point2D.Double(46.64017, 133.9977),
        new Point2D.Double(46.47888, 133.8472),
        new Point2D.Double(46.25363, 133.9016),
        new Point2D.Double(45.82347, 133.4761),
        new Point2D.Double(45.62458, 133.4702),
        new Point2D.Double(45.45083, 133.1491),
        new Point2D.Double(45.05694, 133.0253),
        new Point2D.Double(45.34582, 131.8684),
        new Point2D.Double(44.97388, 131.4691),
        new Point2D.Double(44.83649, 130.953),
        new Point2D.Double(44.05193, 131.298),
        new Point2D.Double(43.53624, 131.1912),
        new Point2D.Double(43.38958, 131.3104),
        new Point2D.Double(42.91645, 131.1285),
        new Point2D.Double(42.74485, 130.4327),
        new Point2D.Double(42.42186, 130.6044),
        new Point2D.Double(42.71416, 130.2468),
        new Point2D.Double(42.88794, 130.2514),
        new Point2D.Double(43.00457, 129.9046),
        new Point2D.Double(42.43582, 129.6955),
        new Point2D.Double(42.44624, 129.3493),
        new Point2D.Double(42.02736, 128.9269),
        new Point2D.Double(42.00124, 128.0566),
        new Point2D.Double(41.58284, 128.3002),
        new Point2D.Double(41.38124, 128.1529),
        new Point2D.Double(41.47249, 127.2708),
        new Point2D.Double(41.79222, 126.9047),
        new Point2D.Double(41.61176, 126.5661),
        new Point2D.Double(40.89694, 126.0118),
        new Point2D.Double(40.47037, 124.8851),
        new Point2D.Double(40.09362, 124.3736),
        new Point2D.Double(39.82777, 124.128),
        new Point2D.Double(39.8143, 123.2422),
        new Point2D.Double(39.67388, 123.2167),
        new Point2D.Double(38.99638, 121.648),
        new Point2D.Double(38.8611, 121.6982),
        new Point2D.Double(38.71909, 121.1873),
        new Point2D.Double(38.91221, 121.0887),
        new Point2D.Double(39.09013, 121.6794),
        new Point2D.Double(39.2186, 121.5994),
        new Point2D.Double(39.35166, 121.7511),
        new Point2D.Double(39.52847, 121.2283),
        new Point2D.Double(39.62322, 121.533),
        new Point2D.Double(39.81138, 121.4683),
        new Point2D.Double(40.00305, 121.881),
        new Point2D.Double(40.50562, 122.2987),
        new Point2D.Double(40.73874, 122.0521),
        new Point2D.Double(40.92194, 121.1775),
        new Point2D.Double(40.1961, 120.4468),
        new Point2D.Double(39.87242, 119.5264),
        new Point2D.Double(39.15693, 118.9715),
        new Point2D.Double(39.04083, 118.3273),
        new Point2D.Double(39.19846, 117.889),
        new Point2D.Double(38.67555, 117.5364),
        new Point2D.Double(38.38666, 117.6722),
        new Point2D.Double(38.16721, 118.0281),
        new Point2D.Double(38.1529, 118.8378),
        new Point2D.Double(37.87832, 119.0355),
        new Point2D.Double(37.30054, 118.9566),
        new Point2D.Double(37.14361, 119.2328),
        new Point2D.Double(37.15138, 119.7672),
        new Point2D.Double(37.35228, 119.8529),
        new Point2D.Double(37.83499, 120.7371),
        new Point2D.Double(37.42458, 121.58),
        new Point2D.Double(37.55256, 122.1282),
        new Point2D.Double(37.41833, 122.1814),
        new Point2D.Double(37.39624, 122.5586),
        new Point2D.Double(37.20999, 122.5972),
        new Point2D.Double(37.02583, 122.4005),
        new Point2D.Double(37.01978, 122.5392),
        new Point2D.Double(36.89361, 122.5047),
        new Point2D.Double(36.84298, 122.1923),
        new Point2D.Double(37.00027, 121.9566),
        new Point2D.Double(36.75889, 121.5944),
        new Point2D.Double(36.61666, 120.7764),
        new Point2D.Double(36.52638, 120.96),
        new Point2D.Double(36.37582, 120.8753),
        new Point2D.Double(36.42277, 120.7062),
        new Point2D.Double(36.14075, 120.6956),
        new Point2D.Double(36.0419, 120.3436),
        new Point2D.Double(36.26345, 120.3078),
        new Point2D.Double(36.19998, 120.0889),
        new Point2D.Double(35.95943, 120.2378),
        new Point2D.Double(35.57893, 119.6475),
        new Point2D.Double(34.88499, 119.1761),
        new Point2D.Double(34.31145, 120.2487),
        new Point2D.Double(32.97499, 120.8858),
        new Point2D.Double(32.63889, 120.8375),
        new Point2D.Double(32.42958, 121.3348),
        new Point2D.Double(32.11333, 121.4412),
        new Point2D.Double(32.02166, 121.7066),
        new Point2D.Double(31.67833, 121.8275),
        new Point2D.Double(31.86639, 120.9444),
        new Point2D.Double(32.09361, 120.6019),
        new Point2D.Double(31.94555, 120.099),
        new Point2D.Double(32.30638, 119.8267),
        new Point2D.Double(32.26277, 119.6317),
        new Point2D.Double(31.90388, 120.1364),
        new Point2D.Double(31.98833, 120.7026),
        new Point2D.Double(31.81944, 120.7196),
        new Point2D.Double(31.30889, 121.6681),
        new Point2D.Double(30.97986, 121.8828),
        new Point2D.Double(30.85305, 121.8469),
        new Point2D.Double(30.56889, 120.9915),
        new Point2D.Double(30.33555, 120.8144),
        new Point2D.Double(30.39298, 120.4586),
        new Point2D.Double(30.19694, 120.15),
        new Point2D.Double(30.31027, 120.5082),
        new Point2D.Double(30.06465, 120.7916),
        new Point2D.Double(30.30458, 121.2808),
        new Point2D.Double(29.96305, 121.6778),
        new Point2D.Double(29.88211, 122.1196),
        new Point2D.Double(29.51167, 121.4483),
        new Point2D.Double(29.58916, 121.9744),
        new Point2D.Double(29.19527, 121.9336),
        new Point2D.Double(29.18388, 121.8119),
        new Point2D.Double(29.37236, 121.7969),
        new Point2D.Double(29.19729, 121.7444),
        new Point2D.Double(29.29111, 121.5611),
        new Point2D.Double(29.1634, 121.4135),
        new Point2D.Double(29.02194, 121.6914),
        new Point2D.Double(28.9359, 121.4908),
        new Point2D.Double(28.72798, 121.6113),
        new Point2D.Double(28.84215, 121.1464),
        new Point2D.Double(28.66993, 121.4844),
        new Point2D.Double(28.34722, 121.6417),
        new Point2D.Double(28.13889, 121.3419),
        new Point2D.Double(28.38277, 121.1651),
        new Point2D.Double(27.98222, 120.9353),
        new Point2D.Double(28.07944, 120.5908),
        new Point2D.Double(27.87229, 120.84),
        new Point2D.Double(27.59319, 120.5812),
        new Point2D.Double(27.45083, 120.6655),
        new Point2D.Double(27.20777, 120.5075),
        new Point2D.Double(27.28278, 120.1896),
        new Point2D.Double(27.14764, 120.4211),
        new Point2D.Double(26.89805, 120.0332),
        new Point2D.Double(26.64465, 120.128),
        new Point2D.Double(26.51778, 119.8603),
        new Point2D.Double(26.78823, 120.0733),
        new Point2D.Double(26.64888, 119.8668),
        new Point2D.Double(26.79611, 119.7879),
        new Point2D.Double(26.75625, 119.5503),
        new Point2D.Double(26.44222, 119.8204),
        new Point2D.Double(26.47388, 119.5775),
        new Point2D.Double(26.33861, 119.658),
        new Point2D.Double(26.36777, 119.9489),
        new Point2D.Double(25.99694, 119.4253),
        new Point2D.Double(26.14041, 119.0975),
        new Point2D.Double(25.93788, 119.354),
        new Point2D.Double(25.99069, 119.7058),
        new Point2D.Double(25.67996, 119.5807),
        new Point2D.Double(25.68222, 119.4522),
        new Point2D.Double(25.35333, 119.6454),
        new Point2D.Double(25.60649, 119.3149),
        new Point2D.Double(25.42097, 119.1053),
        new Point2D.Double(25.25319, 119.3526),
        new Point2D.Double(25.17208, 119.2726),
        new Point2D.Double(25.2426, 118.8749),
        new Point2D.Double(24.97194, 118.9866),
        new Point2D.Double(24.88291, 118.5729),
        new Point2D.Double(24.75673, 118.7631),
        new Point2D.Double(24.52861, 118.5953),
        new Point2D.Double(24.53638, 118.2397),
        new Point2D.Double(24.68194, 118.1688),
        new Point2D.Double(24.44024, 118.0199),
        new Point2D.Double(24.46019, 117.7947),
        new Point2D.Double(24.25875, 118.1237),
        new Point2D.Double(23.62437, 117.1957),
        new Point2D.Double(23.65919, 116.9179),
        new Point2D.Double(23.355, 116.7603),
        new Point2D.Double(23.42024, 116.5322),
        new Point2D.Double(23.23666, 116.7871),
        new Point2D.Double(23.21083, 116.5139),
        new Point2D.Double(22.93902, 116.4817),
        new Point2D.Double(22.73916, 115.7978),
        new Point2D.Double(22.88416, 115.6403),
        new Point2D.Double(22.65889, 115.5367),
        new Point2D.Double(22.80833, 115.1614),
        new Point2D.Double(22.70277, 114.8889),
        new Point2D.Double(22.53305, 114.8722),
        new Point2D.Double(22.64027, 114.718),
        new Point2D.Double(22.81402, 114.7782),
        new Point2D.Double(22.69972, 114.5208),
        new Point2D.Double(22.50423, 114.6136),
        new Point2D.Double(22.55004, 114.2223),
        new Point2D.Double(22.42993, 114.3885),
        new Point2D.Double(22.26056, 114.2961),
        new Point2D.Double(22.36736, 113.9056),
        new Point2D.Double(22.50874, 114.0337),
        new Point2D.Double(22.47444, 113.8608),
        new Point2D.Double(22.83458, 113.606),
        new Point2D.Double(23.05027, 113.5253),
        new Point2D.Double(23.11724, 113.8219),
        new Point2D.Double(23.05083, 113.4793),
        new Point2D.Double(22.87986, 113.3629),
        new Point2D.Double(22.54944, 113.5648),
        new Point2D.Double(22.18701, 113.5527),
        new Point2D.Double(22.56701, 113.1687),
        new Point2D.Double(22.17965, 113.3868),
        new Point2D.Double(22.04069, 113.2226),
        new Point2D.Double(22.20485, 113.0848),
        new Point2D.Double(21.8693, 112.94),
        new Point2D.Double(21.96472, 112.824),
        new Point2D.Double(21.70139, 112.2819),
        new Point2D.Double(21.91611, 111.8921),
        new Point2D.Double(21.75139, 111.9669),
        new Point2D.Double(21.77819, 111.6762),
        new Point2D.Double(21.61264, 111.7832),
        new Point2D.Double(21.5268, 111.644),
        new Point2D.Double(21.52528, 111.0285),
        new Point2D.Double(21.21138, 110.5328),
        new Point2D.Double(21.37322, 110.3944),
        new Point2D.Double(20.84381, 110.1594),
        new Point2D.Double(20.84083, 110.3755),
        new Point2D.Double(20.64, 110.3239),
        new Point2D.Double(20.48618, 110.5274),
        new Point2D.Double(20.24611, 110.2789),
        new Point2D.Double(20.2336, 109.9244),
        new Point2D.Double(20.4318, 110.0069),
        new Point2D.Double(20.92416, 109.6629),
        new Point2D.Double(21.44694, 109.9411),
        new Point2D.Double(21.50569, 109.6605),
        new Point2D.Double(21.72333, 109.5733),
        new Point2D.Double(21.49499, 109.5344),
        new Point2D.Double(21.39666, 109.1428),
        new Point2D.Double(21.58305, 109.1375),
        new Point2D.Double(21.61611, 108.911),
        new Point2D.Double(21.79889, 108.8702),
        new Point2D.Double(21.59888, 108.7403),
        new Point2D.Double(21.93562, 108.4692),
        new Point2D.Double(21.59014, 108.5125),
        new Point2D.Double(21.68999, 108.3336),
        new Point2D.Double(21.51444, 108.2447),
        new Point2D.Double(21.54241, 107.99),
        new Point2D.Double(21.66694, 107.7831),
        new Point2D.Double(21.60526, 107.3627),
        new Point2D.Double(22.03083, 106.6933),
        new Point2D.Double(22.45682, 106.5517),
        new Point2D.Double(22.76389, 106.7875),
        new Point2D.Double(22.86694, 106.7029),
        new Point2D.Double(22.91253, 105.8771),
        new Point2D.Double(23.32416, 105.3587),
        new Point2D.Double(23.18027, 104.9075),
        new Point2D.Double(22.81805, 104.7319),
        new Point2D.Double(22.6875, 104.3747),
        new Point2D.Double(22.79812, 104.1113),
        new Point2D.Double(22.50387, 103.9687),
        new Point2D.Double(22.78287, 103.6538),
        new Point2D.Double(22.58436, 103.5224),
        new Point2D.Double(22.79451, 103.3337),
        new Point2D.Double(22.43652, 103.0304),
        new Point2D.Double(22.77187, 102.4744),
        new Point2D.Double(22.39629, 102.1407),
        new Point2D.Double(22.49777, 101.7415),
        new Point2D.Double(22.20916, 101.5744),
        new Point2D.Double(21.83444, 101.7653),
        new Point2D.Double(21.14451, 101.786),
        new Point2D.Double(21.17687, 101.2919),
        new Point2D.Double(21.57264, 101.1482),
        new Point2D.Double(21.76903, 101.099),
        new Point2D.Double(21.47694, 100.6397),
        new Point2D.Double(21.43546, 100.2057),
        new Point2D.Double(21.72555, 99.97763),
        new Point2D.Double(22.05018, 99.95741),
        new Point2D.Double(22.15592, 99.16785),
        new Point2D.Double(22.93659, 99.56484),
        new Point2D.Double(23.08204, 99.5113),
        new Point2D.Double(23.18916, 98.92747),
        new Point2D.Double(23.97076, 98.67991),
        new Point2D.Double(24.16007, 98.89073),
        new Point2D.Double(23.92999, 97.54762),
        new Point2D.Double(24.26055, 97.7593),
        new Point2D.Double(24.47666, 97.54305),
        new Point2D.Double(24.73992, 97.55255),
        new Point2D.Double(25.61527, 98.19109),
        new Point2D.Double(25.56944, 98.36137),
        new Point2D.Double(25.85597, 98.7104),
        new Point2D.Double(26.12527, 98.56944),
        new Point2D.Double(26.18472, 98.73109),
        new Point2D.Double(26.79166, 98.77777),
        new Point2D.Double(27.52972, 98.69699),
        new Point2D.Double(27.6725, 98.45888),
        new Point2D.Double(27.54014, 98.31992),
        new Point2D.Double(28.14889, 98.14499),
        new Point2D.Double(28.54652, 97.55887),
        new Point2D.Double(28.22277, 97.34888),
        new Point2D.Double(28.46749, 96.65387),
        new Point2D.Double(28.35111, 96.40193),
        new Point2D.Double(28.525, 96.34027),
        new Point2D.Double(28.79569, 96.61373),
        new Point2D.Double(29.05666, 96.47083),
        new Point2D.Double(28.90138, 96.17532),
        new Point2D.Double(29.05972, 96.14888),
        new Point2D.Double(29.25757, 96.39172),
        new Point2D.Double(29.46444, 96.08315),
        new Point2D.Double(29.03527, 95.38777),
        new Point2D.Double(29.33346, 94.64751),
        new Point2D.Double(29.07348, 94.23456),
        new Point2D.Double(28.6692, 93.96172),
        new Point2D.Double(28.61876, 93.35194),
        new Point2D.Double(28.3193, 93.22205),
        new Point2D.Double(28.1419, 92.71044),
        new Point2D.Double(27.86194, 92.54498),
        new Point2D.Double(27.76472, 91.65776),
        new Point2D.Double(27.945, 91.66277),
        new Point2D.Double(28.08111, 91.30138),
        new Point2D.Double(27.96999, 91.08693),
        new Point2D.Double(28.07958, 90.3765),
        new Point2D.Double(28.24257, 90.38898),
        new Point2D.Double(28.32369, 89.99819),
        new Point2D.Double(28.05777, 89.48749),
        new Point2D.Double(27.32083, 88.91693));

    private static final List<Point2D.Double> taiwan = Lists.newArrayList(
        new Point2D.Double(25.13474, 121.4441),
        new Point2D.Double(25.28361, 121.5632),
        new Point2D.Double(25.00722, 122.0004),
        new Point2D.Double(24.85028, 121.8182),
        new Point2D.Double(24.47638, 121.8397),
        new Point2D.Double(23.0875, 121.3556),
        new Point2D.Double(21.92791, 120.7196),
        new Point2D.Double(22.31277, 120.6103),
        new Point2D.Double(22.54044, 120.3071),
        new Point2D.Double(23.04437, 120.0539),
        new Point2D.Double(23.61708, 120.1112),
        new Point2D.Double(25.00166, 121.0017),
        new Point2D.Double(25.13474, 121.4441));

    private static final List<Point2D.Double> hainan = Lists.newArrayList(
        new Point2D.Double(19.52888, 110.855),
        new Point2D.Double(19.16761, 110.4832),
        new Point2D.Double(18.80083, 110.5255),
        new Point2D.Double(18.3852, 110.0503),
        new Point2D.Double(18.39152, 109.7594),
        new Point2D.Double(18.19777, 109.7036),
        new Point2D.Double(18.50562, 108.6871),
        new Point2D.Double(19.28028, 108.6283),
        new Point2D.Double(19.76, 109.2939),
        new Point2D.Double(19.7236, 109.1653),
        new Point2D.Double(19.89972, 109.2572),
        new Point2D.Double(19.82861, 109.4658),
        new Point2D.Double(19.99389, 109.6108),
        new Point2D.Double(20.13361, 110.6655),
        new Point2D.Double(19.97861, 110.9425),
        new Point2D.Double(19.63829, 111.0215),
        new Point2D.Double(19.52888, 110.855));

    private static final List<Point2D.Double> chongming = Lists.newArrayList(
        new Point2D.Double(31.80054, 121.2039),
        new Point2D.Double(31.49972, 121.8736),
        new Point2D.Double(31.53111, 121.5464),
        new Point2D.Double(31.80054, 121.2039));
}
